import { AxiosRequestConfig } from "axios";
import type { DeleteParams, PaginationParam, PaginationResult, SearchModel } from "./models";
import req from "./req";
import { RequestMethodEnum } from "./req/httpEnum";

export interface CURDApiOptions {
  //获取所有数据URL，不分页
  getDataUrl?: string;
  getDataMethod?: RequestMethodEnum;
  //获取分页数据URL
  getPageUrl?: string;
  getPageMethod?: RequestMethodEnum;
  //获取详细信息,目前只支持根据对应主键id获取，即参数是{[idKey]: idValue}
  getDetailUrl?: string;
  getDetailMethod?: RequestMethodEnum;
  //增删改统一一个URL，利用post delete put区分
  cudUrl?: string;
  //增删改各对应一个URL
  createUrl?: string;
  createMethod?: RequestMethodEnum;
  updateUrl?: string;
  updateMethod?: RequestMethodEnum;
  deleteUrl?: string;
  deleteMethod?: RequestMethodEnum;
  //删除参数key
  deleteParamKey?: "data" | "params";
  restful?: boolean;
  onDeleteSuccess?: () => void;
  getUpdateConfig?: (data: any) => AxiosRequestConfig;
}
export default class CURD<T = any, K = any> {
  options: CURDApiOptions;
  constructor(options: CURDApiOptions) {
    const defaultOptions = {
      getDataMethod: RequestMethodEnum.GET,
      getPageMethod: RequestMethodEnum.GET,
      createMethod: RequestMethodEnum.POST,
      updateMethod: RequestMethodEnum.PUT,
      deleteMethod: RequestMethodEnum.DELETE,
      getDetailMethod: RequestMethodEnum.GET,
    };
    for (let i in defaultOptions) {
      if (!options[i]) {
        options[i] = defaultOptions[i];
      }
    }
    // options = Object.assign(
    //   {
    //     getDataMethod: RequestMethodEnum.GET,
    //     getPageMethod: RequestMethodEnum.GET,
    //     createMethod: RequestMethodEnum.POST,
    //     updateMethod: RequestMethodEnum.PUT,
    //     deleteMethod: RequestMethodEnum.DELETE,
    //     getDetailMethod: RequestMethodEnum.GET,
    //   },
    //   options
    // );
    this.options = options;
    if (options.cudUrl) {
      options.createUrl = options.updateUrl = options.deleteUrl = options.cudUrl;
    } else {
      if (!options.createUrl) {
        this.create = undefined;
      }
      if (!options.updateUrl) {
        this.update = undefined;
      }
      if (!options.deleteUrl) {
        this.delete = undefined;
      }
    }
    if (!options.getDetailUrl) {
      this.getDetail = undefined;
    }
  }
  getData(params?: K | SearchModel) {
    const method = (this.options.getDataMethod as string).toLowerCase();
    return req[method]<T[]>(
      {
        [this.options.getDataMethod === RequestMethodEnum.POST ? "data" : "params"]: params,
        url: this.options.getDataUrl,
      },
      {
        useGlobalLoading: false,
      }
    );
  }
  getPage(params: PaginationParam<K>) {
    const method = (this.options.getPageMethod as string).toLowerCase();
    return req[method]<PaginationResult<T>>(
      {
        [method === "get" ? "params" : "data"]: params,
        url: this.options.getPageUrl,
      },
      {
        useGlobalLoading: false,
      }
    );
  }
  getPageInResponse(params: PaginationParam<K>) {
    return req.commonGetResponse(this.options.getPageUrl as string, params, { useGlobalLoading: false });
  }
  getDetail?(params: any) {
    const method = (this.options.getDetailMethod as string).toLowerCase();
    return req[method]<T>(
      {
        [method === "get" ? "params" : "data"]: params,
        url: this.options.getDetailUrl,
      },
      {
        useGlobalLoading: false,
      }
    );
  }
  create?(params: T) {
    const method = this.options.createUrl ? (this.options.createMethod as string).toLowerCase() : "post";
    return req[method]<T>(
      {
        [method === "get" ? "params" : "data"]: params,
        url: this.options.createUrl,
      },
      {
        useGlobalLoading: true,
      }
    );
  }
  update?(params: any) {
    const method = this.options.updateUrl ? (this.options.updateMethod as string).toLowerCase() : "post";
    return req[method]<T>(
      this.options.getUpdateConfig
        ? this.options.getUpdateConfig(params)
        : {
            [method === "get" ? "params" : "data"]: params,
            url: this.options.updateUrl + (this.options.restful ? `/${params.id}` : ""),
          },
      {
        useGlobalLoading: true,
      }
    );
  }
  async delete?(params: any) {
    const method = this.options.deleteUrl ? (this.options.deleteMethod as string).toLowerCase() : "post";
    let paramKey = "data";
    if (this.options.deleteParamKey) {
      paramKey = this.options.deleteParamKey;
    } else {
      paramKey = method === "get" ? "params" : "data";
    }
    const re = await req[method]<boolean>(
      {
        [paramKey]: { [params.idKey]: params.idValue },
        url: this.options.deleteUrl,
      },
      {
        useGlobalLoading: true,
      }
    );
    if (re !== null) {
      this.options.onDeleteSuccess && this.options.onDeleteSuccess();
    }
    return re;
  }
}
